﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;

namespace Common.Util
{
    public class RijndaelEncryptor
    {
        /// <summary>
        /// 使用对称算法加密
        /// </summary>
        public static string Encrypt(string plainText, string key, string IV)
        {
            try
            {
                string result = string.Empty;
                using (RijndaelManaged rijAlg = new RijndaelManaged())
                {
                    rijAlg.Mode = CipherMode.CBC;
                    byte[] buffer = Encoding.UTF8.GetBytes(plainText);
                    byte[] bytes = Encoding.ASCII.GetBytes(key);
                    byte[] buffer3 = Encoding.ASCII.GetBytes(IV);
                    rijAlg.Key = bytes;
                    rijAlg.IV = buffer3;
                    ICryptoTransform transform = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                    using (MemoryStream stream = new MemoryStream())
                    {
                        stream.Write(buffer, 0, buffer.Length);
                        new CryptoStream(stream, transform, CryptoStreamMode.Write);
                        byte[] buffer4 = stream.ToArray();
                        result = Convert.ToBase64String(stream.ToArray());
                    }
                }
                return result;
            }
            catch (Exception err)
            {
                throw err;
            }
        }


        public static string Decrypt(string cipherText, string key, string IV)
        {
            try
            {
                string result = string.Empty;
                using (RijndaelManaged rijAlg = new RijndaelManaged())
                {
                    rijAlg.Mode = CipherMode.CBC;
                    byte[] buffer = Convert.FromBase64String(cipherText);
                    byte[] bytes = Encoding.ASCII.GetBytes(key);
                    byte[] buffer3 = Encoding.ASCII.GetBytes(IV);
                    rijAlg.Key = bytes;
                    rijAlg.IV = buffer3;
                    ICryptoTransform transform = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                    using (MemoryStream stream = new MemoryStream())
                    {
                        stream.Write(buffer, 0, buffer.Length);
                        new CryptoStream(stream, transform, CryptoStreamMode.Write);
                        byte[] buffer4 = stream.ToArray();
                        result = Encoding.UTF8.GetString(buffer4);
                    }
                }
                return result;
            }
            catch (Exception err)
            {
                throw err;
            }
        }


        public static string EncryptStringToBytes(string plainText, string Key, string IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;
            // Create an Rijndael object
            // with the specified key and IV.
            using (Rijndael rijAlg = Rijndael.Create())
            {
                rijAlg.Key = Convert.FromBase64String(Key);
                rijAlg.IV = Convert.FromBase64String(IV);

                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            // Return the encrypted bytes from the memory stream.
            //return encrypted;
            return Convert.ToBase64String(encrypted);

        }

        public static string DecryptStringFromBytes(string cipherText, string Key, string IV)
        {

            byte[] cipherTextbyte = Convert.FromBase64String(cipherText);

            // Check arguments.
            if (cipherTextbyte == null || cipherTextbyte.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Rijndael object
            // with the specified key and IV.
            using (Rijndael rijAlg = Rijndael.Create())
            {
                rijAlg.Key = Convert.FromBase64String(Key);
                rijAlg.IV = Convert.FromBase64String(IV);

                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherTextbyte))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;

        }

        public static bool IsBase64Formatted(string input)
        {
            try
            {
                Convert.FromBase64String(input);
                return true;
            }
            catch { return false; }
        }

        /// <summary>
        /// 256位AES加密
        /// </summary>
        /// <param name="toEncrypt"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AES256Encrypt(string toEncrypt, string key)
        {
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        /// <summary>
        /// 256位AES解密
        /// </summary>
        /// <param name="toDecrypt"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AES256Decrypt(string toDecrypt, string key)
        {
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Encoding.UTF8.GetString(resultArray);
        }


        /// <summary>
        /// 256位AES加密
        /// </summary>
        /// <param name="toEncryptArray"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static byte[] AES256Encrypt(byte[] toEncryptArray, string key)
        {
            byte[] keyArray = Convert.FromBase64String(key);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return resultArray;
        }

        /// <summary>
        /// 256位AES解密
        /// </summary>
        /// <param name="toDecrypt"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static byte[] AES256Decrypt(byte[] toEncryptArray, string key)
        {
            byte[] keyArray = Convert.FromBase64String(key);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return resultArray;
        }




        public static byte[] AESEncrypt(byte[] toEncryptArray, string Key, string IV)
        {
            // Check arguments.
            if (toEncryptArray == null || toEncryptArray.Length <= 0)
                throw new ArgumentNullException("toEncryptArray");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;
            try
            {

                using (Rijndael rijAlg = Rijndael.Create())
                {
                    rijAlg.Key = Encoding.ASCII.GetBytes(Key);
                    rijAlg.IV = Encoding.ASCII.GetBytes(IV);
                    ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
                    encrypted = encryptor.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
            return encrypted;

        }

        public static byte[] AESDecrypt(byte[] toEncryptArray, string Key, string IV)
        {
            // Check arguments.
            if (toEncryptArray == null || toEncryptArray.Length <= 0)
                throw new ArgumentNullException("toEncryptArray");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            byte[] plainbBytes = null;

            try
            {
                RijndaelManaged rDel = new RijndaelManaged();
                rDel.Key = Encoding.ASCII.GetBytes(Key);
                rDel.IV = Encoding.ASCII.GetBytes(IV);

                ICryptoTransform cTransform = rDel.CreateDecryptor();
                plainbBytes = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            }
            catch (Exception ex)
            {

                throw ex;
            }
            return plainbBytes;

        }

    }
}

